package com.sz.biz.logistics.base.service.impl;

import com.sz.biz.common.constants.ErrorCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.logistics.base.dto.AirlineDetailDto;
import com.sz.biz.logistics.base.dto.AirlineDto;
import com.sz.biz.logistics.base.dto.FlightDetailDto;
import com.sz.biz.logistics.base.dto.FlightDto;
import com.sz.biz.logistics.base.entity.AirplaneModel;
import com.sz.biz.logistics.base.entity.CarrierCompany;
import com.sz.biz.logistics.base.entity.Flight;
import com.sz.biz.logistics.base.entity.FlightDetail;
import com.sz.biz.logistics.base.service.*;
import com.sz.biz.logistics.constants.BaseConstants;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.DaoSupport;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.dto.ResultDto;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.service.AbstractService;
import com.sz.common.base.utils.CollectionUtils;
import com.sz.common.base.utils.EntityUtils;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * Function: 航班flightService <br>
 * Author: wentao.chang <br>
 * Date: 2017-08-04 15:41:00
 */
@Service("flightService")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class FlightServiceImpl extends AbstractService implements FlightService {

    @Resource(name = "daoSupport")
    private DaoSupport dao;
    @Autowired
    private AirlineService airlineService;
    @Autowired
    private AirlineDetailService airlineDetailService;

    @Autowired
    private FlightDetailService flightDetailService;

    @Autowired
    private CarrierCompanyService carrierCompanyService;
    @Autowired
    private AirplaneModelService airplaneModelService;

    @Override
    public int save(FlightDto flightDto) {
        List<FlightDetailDto> detailDtoList = flightDto.getDetails();
        this.judgeParam(detailDtoList);
        Flight flight = new Flight();
        EntityUtils.copyPropertiesIgnoreNull(flightDto, flight);
        // 检查数据不能重复
        checkCode(flight.getCode(), null);
        flight.setCreateUserId(PrincipalUtils.getAccountId());
        flight.setLastUpdateUserId(PrincipalUtils.getAccountId());
        dao.save("FlightMapper.insert", flight);
        saveDetail(flight.getId(), flightDto);
        // 保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_FLIGHT", flight);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_FLIGHT, UserActions.ADD, "新建空运航班",
                dataBackup);
        return flight.getId();
    }

    @Override
    public int update(Integer id, FlightDto flightDto) {

        List<FlightDetailDto> detailDtoList = flightDto.getDetails();
        this.judgeParam(detailDtoList);

        Flight flightExist = findSimpleById(id);
        if (flightExist.getIsDeleted()) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_HAS_DELETED, id);
        }
        Flight flight = new Flight();
        EntityUtils.copyPropertiesIgnoreNull(flightDto, flight);
        // 检查数据不能重复
        checkCode(flight.getCode(), id);
        flight.setLastUpdateUserId(PrincipalUtils.getAccountId());
        flight.setId(id);
        dao.update("FlightMapper.update", flight);
        flightDetailService.deleteByFlightId(id);
        saveDetail(flight.getId(), flightDto);
        // 保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_FLIGHT", flight);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_FLIGHT, UserActions.UPDATE, "修改空运航班",
                dataBackup);
        return id;
    }

    private void judgeParam(List<FlightDetailDto> detailDtoList) {
        if (!CollectionUtils.isEmpty(detailDtoList)) {
            for (int i = 0; i < detailDtoList.size(); i++) {
                FlightDetailDto detailDto = detailDtoList.get(i);
                if (i % 2 == 1) {   //奇数
                    if (ObjectUtils.isEmpty(detailDto.getArriveTime())) {
                        throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "第"+i+"个到达时间不能为空");
                    }
                } else {//偶数
                    if (ObjectUtils.isEmpty(detailDto.getStartTime())) {
                        throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "第"+i+"个起飞时间不能为空");
                    }
                }
            }
        }
    }

    private void saveDetail(Integer flightId, FlightDto flightDto) {
        if (!CollectionUtils.isEmpty(flightDto.getDetails())) {
            final Integer[] i = {1};
            flightDto.getDetails().forEach(item -> {
                item.setFlightId(flightId);
                item.setOrdinal(i[0]++);
            });
            flightDetailService.save(flightDto.getDetails());
        }
    }

    @Override
    public void checkCode(String code, Integer id) {
        Map<String, Object> map = new HashMap<>(15);
        map.put("code", code);
        map.put("id", id);
        Flight shipExist = (Flight) dao.findForObject("FlightMapper.checkCode", map);
        if (shipExist != null) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_CODE_EXIST, ModuleNames.BIZ_FLIGHT);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteByIds(List<Integer> ids) {
        dao.update("FlightMapper.deleteByIds", ids);
        // 保存操作日志
        Map<String, Object> dataBackup = new HashMap<>(15);
        dataBackup.put("DELETE_FLIGHT", ids);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_FLIGHT, UserActions.DELETE, "删除空运航班",
                dataBackup);

    }

    @Override
    public FlightDto findById(int id) {
        ParamData pd = new ParamData();
        pd.put("id", id);
        Flight flight = (Flight) dao.findForObject("FlightMapper.findById", pd);
        FlightDto flightDto = new FlightDto();
        BeanUtils.copyProperties(flight, flightDto);

        if (flight.getCarrierCompanyId() != null) {
            List<CarrierCompany> ccs = carrierCompanyService.findByIds(Collections.singletonList(flight.getCarrierCompanyId()));
            Map<String, CarrierCompany> ccMap = EntityUtils.getStringKeyMapFromBeans(ccs, "id");
            if (ccMap.get(flight.getCarrierCompanyId() + "") != null) {
                CarrierCompany cc = ccMap.get(flight.getCarrierCompanyId() + "");
                flightDto.setCarrierCompanyName(cc.getName() + "(" + cc.getFigureCode() + ")");
            }
        }
        getAirlineName(flight.getAirlineId(), flightDto);
        if (flight.getAirplaneModelId() != null) {
            AirplaneModel mol = airplaneModelService.getById(flight.getAirplaneModelId());
            flightDto.setAirplaneModelName(mol.getName() + "(" + mol.getIcao() + ")");
        }
        return flightDto;
    }


    @Override
    public ResultDto findFlightListPage(QueryParams params) {
        ParamData pd = this.convertQueryParams(params);
        // 调用方法查询数据
        List<Flight> list = dao.findForList("FlightMapper.flightListPage", pd, Flight.class);
        List<FlightDto> dtos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            List<CarrierCompany> ccs = carrierCompanyService.findByIds(EntityUtils.getIntPropListFromBeans(list, "carrierCompanyId"));
            Map<String, CarrierCompany> ccMap = EntityUtils.getStringKeyMapFromBeans(ccs, "id");


            list.forEach(flight -> {
                FlightDto dto = new FlightDto();
                BeanUtils.copyProperties(flight, dto);

                if (ccMap.get(flight.getCarrierCompanyId() + "") != null) {
                    dto.setCarrierCompanyName(ccMap.get(flight.getCarrierCompanyId() + "").getName());
                }
                if (flight.getAirplaneModelId() != null) {
                    dto.setAirplaneModelName(airplaneModelService.getById(flight.getAirplaneModelId()).getName());
                }
                getAirlineName(flight.getAirlineId(), dto);
                dtos.add(dto);
            });
            for (FlightDto dto : dtos) {
                List<FlightDetailDto> details = dto.getDetails();

                if (!CollectionUtils.isEmpty(details)) {
                    dto.setStartName(details.get(0).getAirportName());
                    dto.setStartTriadCode(details.get(0).getAirportTriadCode());
                    dto.setStartTime(details.get(0).getStartTime());
                    if (details.size() >= 2) {
                        dto.setEndName(details.get(details.size() - 1).getAirportName());
                        dto.setEndTriadCode(details.get(details.size() - 1).getAirportTriadCode());
                        dto.setEndTime(details.get(details.size() - 1).getArriveTime());
                    }

                }
            }
        }
        QResultDto dto = new QResultDto();
        dto.setData(dtos);
        dto.setPagination(pd.getPagination());
        return dto;
    }

    private void getAirlineName(Integer airlineId, FlightDto flightDto) {
        if (airlineId != null) {
            AirlineDto airline = airlineService.findById(airlineId);
            List<AirlineDetailDto> ports = airline.getAirports();
            Map<String, AirlineDetailDto> portsMap = EntityUtils.getStringKeyMapFromBeans(ports, "airportId");
            List<FlightDetail> flightDetails = flightDetailService.findByFlightId(flightDto.getId());
            flightDetails.forEach(flightDetail -> {
                FlightDetailDto detail = new FlightDetailDto();
                BeanUtils.copyProperties(flightDetail, detail);
                if (portsMap.get(detail.getAirportId() + "") != null) {
                    detail.setAirportName(portsMap.get(detail.getAirportId() + "").getAirportName());
                    detail.setAirportTriadCode(portsMap.get(detail.getAirportId() + "").getAirportTriadCode());
                }
                flightDto.getDetails().add(detail);
            });

            flightDto.setAirlineName(airline.getName() + "(" + airline.getCode() + ")");
            if (flightDto.getType() != null) {
                if (flightDto.getType() == BaseConstants.FlightType.SELF) {
                    flightDto.setTypeName("自营航班");
                }
                if (flightDto.getType() == BaseConstants.FlightType.TRUCK) {
                    flightDto.setTypeName("卡车航班");
                }
                if (flightDto.getType() == BaseConstants.FlightType.SPA) {
                    flightDto.setTypeName("SPA航班");
                }
            }
        }
    }

    /**
     * 根据ids查询空运航班信息
     *
     * @param id id
     * @return Flight
     */
    @Override
    public Flight findSimpleById(int id) {
        return (Flight) dao.findForObject("FlightMapper.findById", id);
    }

    /**
     * 根据ids查询空运航班信息
     *
     * @param ids ids
     * @return Flight
     */
    @Override
    public List<Flight> findSimpleByIds(List<Integer> ids) {
        return dao.findForList("FlightMapper.findByIds", ids, Flight.class);
    }

    /**
     * 根据条件分页查询空运航班短接口
     *
     * @param params params
     * @return ResultDto
     */
    @Override
    public ResultDto findFlightShortListPage(QueryParams params) {
        ParamData pd = this.convertQueryParams(params);
        // 调用方法查询数据
        List<Flight> list = dao.findForList("FlightMapper.flightShortListPage", pd, Flight.class);
        QResultDto dto = new QResultDto();
        dto.setData(list);
        dto.setPagination(pd.getPagination());
        return dto;
    }


    @Override
    protected String getMapperNamespace() {
        return "FlightMapper";
    }

}
